﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using DICE_GS;

public class SkillResInfo
{
	public GameObject skillResPrefab;
	public AudioClip skillSound;
	public float needClearInSeconds;
	public AbnormalType abnormalType;
	public int abnormalParam;
	public bool isNeedOffsetAdjust;
	public bool isOnActiveCard;
	public bool isInstantDestroy;
	public bool dontRemoveByAbnormal;

	public SkillResInfo(float _needClearInSeconds, bool _isNeedOffsetAdjust, bool _isOnCard, bool _isInstantDestroy, bool _dontRemoveByAbnormal)
	{
		needClearInSeconds = _needClearInSeconds;
		isNeedOffsetAdjust = _isNeedOffsetAdjust;
		isOnActiveCard = _isOnCard;
		isInstantDestroy = _isInstantDestroy;
		dontRemoveByAbnormal = _dontRemoveByAbnormal;
	}
}


public class SkillManager : MonoBehaviour {
	
	private static SkillManager instance;

	public static SkillManager Instance{
		get{
			return instance;
		}
	}	

	void Awake()
	{
		instance = this;
		//needFX.Add (100034); //modify_move_cost (2)
		//needFX.Add (100039);
		//needFX.Add (100040);
		//needFX.Add (100041);

		//needFX.Add (100043);
		//needFX.Add (100044);

		//needOffsetAdjust.Add (100034);

		//needClearInSeconds.Add (100034, 20); //for test temp

		//needClearInSeconds.Add (100039, 2);
		//needClearInSeconds.Add (100040, 2);
		//needClearInSeconds.Add (100041, 2);
	}
	
	public bool bWaitSelectTarget;
	public PC_OP_USE_SKILL reservedPacketToCast;
	public int skillID_1;
	public int skillID_2;
	public int skillID_3;
	public int skillID_4;
	GameObject selectUI;
	EnemyChoice enemyChoice;


	static Dictionary<int, SkillResInfo> needFX = new Dictionary<int, SkillResInfo>()
	{
		{100034, new SkillResInfo(0,true,false,false,false)},
		{100039, new SkillResInfo(2,false,false,false,false)},
		{100040, new SkillResInfo(2,false,false,false,false)},
		{100041, new SkillResInfo(2,false,false,false,false)},
		{100008, new SkillResInfo(0,false,true,true,false)},
		{100044, new SkillResInfo(0,false,true,true,false)},
		{500018, new SkillResInfo(2.5f,false,false,true,false)},
		{100029, new SkillResInfo(2.5f,false,false,true,true)},
		{100037, new SkillResInfo(2.5f,false,false,true,true)},
		{100042, new SkillResInfo(1.0f,false,false,false,true)},//mp_drain 
		{100045, new SkillResInfo(3.0f,false,false,false,true)},//dispell
		{100046, new SkillResInfo(3.0f,false,false,false,true)},//dispell

	};
	//List<int> needFX = new List<int>();
	//List<int> needOffsetAdjust = new List<int>();
	//Dictionary<int , float > needClearInSeconds = new Dictionary<int, float>();
	//Dictionary<int, GameObject> skillResPrefab = new Dictionary<int, GameObject>();
	//Dictionary<int, AudioClip> skillSound = new Dictionary<int, AudioClip>();
	Dictionary<int, List<GameObject> > skillEffInstance = new Dictionary<int, List<GameObject>>();
	//public Dictionary<int, int> abnormal_SkillLink = new Dictionary<int, int>();
	
	public void WaitSelectTarget(bool bWait)
	{
		glog.debug("WaitSelectTarget="+bWait);
		bWaitSelectTarget = bWait;
		
		if(bWait)
		{
			int nCount = 0;
			int nOrder = 2;
			for(int i=2;i<=4;i++)
			{
				if(HudManager.Instance.charPanel[i]!=null)
				{
					nOrder = i;
					nCount++;
				}
			}			
			
			UIManager.Instance.ShowRollPanel(false);


			if(nCount==0)
			{
				bWaitSelectTarget = false;
				//ActivateSelectUI(false);
			}
			else if(nCount==1)
			{
				bWaitSelectTarget = false;
				//ActivateSelectUI(false);
				CastSkillToTarget( HudManager.Instance.charOrderSidDic[nOrder]  );
			}
			else if(nCount==2)
			{
				int sid2 = HudManager.Instance.charOrderSidDic[2];
				int sid3 = HudManager.Instance.charOrderSidDic[3];
				if( StageManagerWrapper.GetBoardPerson(sid2).isRetired)
				{
					bWaitSelectTarget = false;
					//ActivateSelectUI(false);
					CastSkillToTarget( sid3);
				}
				else if( StageManagerWrapper.GetBoardPerson(sid3).isRetired)
				{
					bWaitSelectTarget = false;
					//ActivateSelectUI(false);
					CastSkillToTarget( sid2);
				}
				else
				{
					MakeSelectUI();
					ActivateSelectUI(true);
					SetCharPanel(2, "Panel_Char_Pos2_1");
					SetCharPanel(3, "Panel_Char_Pos2_2");			
				}
			}
			else if(nCount==3)
			{
				MakeSelectUI();
				ActivateSelectUI(true);
			
				int sid2 = HudManager.Instance.charOrderSidDic[2];
				int sid3 = HudManager.Instance.charOrderSidDic[3];
				int sid4 = HudManager.Instance.charOrderSidDic[4];
				if( !StageManagerWrapper.GetBoardPerson(sid2).isRetired)
					SetCharPanel(2, "Panel_Char_Pos1");
				if( !StageManagerWrapper.GetBoardPerson(sid3).isRetired)
					SetCharPanel(3, "Panel_Char_Pos2");
				if( !StageManagerWrapper.GetBoardPerson(sid4).isRetired)
					SetCharPanel(4, "Panel_Char_Pos3");
			}
		}
		else
		{
			ActivateSelectUI(false);
		}
	}
	
	void ActivateSelectUI(bool bActive)
	{
		if(selectUI!=null)
		{
			if(selectUI.activeSelf && !bActive)
				enemyChoice.StopTimer();
			selectUI.SetActive(bActive);
			enemyChoice = selectUI.GetComponent<EnemyChoice>();
			enemyChoice.HideAll();
			if(bActive)
				enemyChoice.StartTimer();

		}
	}
	
	void MakeSelectUI()
	{
		if(selectUI==null)
		{
			GameObject uiprefab = Resources.Load("Prefabs/UI/Panel_EnemyChoice") as GameObject;
			selectUI = NGUITools.AddChild(UIManager.Instance.centerAnchor, uiprefab);
		}		
	}
	
	void SetCharPanel(int nOrder, string posStr)
	{
		GameObject charPanel = enemyChoice.enemySprite[nOrder-2];
		charPanel.SetActive(true);
		charPanel.transform.localPosition = selectUI.transform.FindChild(posStr).localPosition;
		charPanel.GetComponent<EnemyChoiceEnemy>().Init( HudManager.Instance.charOrderSidDic[nOrder] , nOrder);
	//	charGo.GetComponent<UIPressCharImage>().bForSkillTarget = true;

	
	}
	
	public void ReserveSkillToCast(PC_OP_USE_SKILL skillpacket)
	{
		reservedPacketToCast = skillpacket;
	}
	
	public void CastSkillToTarget(int sid)
	{
		WaitSelectTarget(false);
		if(reservedPacketToCast==null)
			return;
		reservedPacketToCast.TargetID = sid;
		glog.debug("cast skill to player "+sid);
		//CNetworkManager.Instance.SendPacket(reservedPacketToCast.Protocol, reservedPacketToCast.GetParam());
		if(BoardManager.Instance.boardPerson_me.pawnType != GAME_PAWN_TYPE.BOT)
			CNetworkManager.Instance.SendPacket(reservedPacketToCast);
		else
			Debug.LogError("current BOT.  dont skill cast");
		reservedPacketToCast=null;
	}
	
	public void LoadResource(int skill_id, AbnormalType abType, int abParam)
	{
		if(needFX.ContainsKey(skill_id))
		{
			if(needFX[skill_id].skillResPrefab==null)
			{
				Object [] temp = Resources.LoadAll("Prefabs/SkillFX/"+skill_id.ToString()+"/FX");
				Debug.LogError("Load Skill resoruce once  "+skill_id);
				if(temp!=null && temp.Length>0)
				{
					glog.debug("prefab ok");
					needFX[skill_id].skillResPrefab = (GameObject)temp[0];
					needFX[skill_id].abnormalType = abType;
					needFX[skill_id].abnormalParam = abParam;
				}
			}

		}
	}

	void CreateEffInstance(BoardPerson person, int skill_id)
	{
		var list = skillEffInstance[skill_id];
		GameObject go = Instantiate( needFX[skill_id].skillResPrefab) as GameObject;
		go.name = skill_id.ToString();

		list.Add( go);

		SetEffPosition(go, person, skill_id);
	}

	void SetEffPosition(GameObject go, BoardPerson person, int skill_id)
	{
		SkillResInfo skillResInfo = needFX[skill_id];
		Vector3 newPos = skillResInfo.skillResPrefab.transform.position;

		if(skillResInfo.isOnActiveCard)
		{
			CardManager.Instance.EffectOnActiveCard(person.SID, go);
		}
		else
		{
			go.transform.parent = person.transform;
			if( skillResInfo.isNeedOffsetAdjust )
				newPos.y += IngameSetting.Instance.GetCharOffset(person.charID);
		}

		go.transform.localPosition = newPos;
		go.transform.localRotation = skillResInfo.skillResPrefab.transform.rotation;
		go.transform.localScale = skillResInfo.skillResPrefab.transform.localScale;

		ParticleSystem [] particles = go.GetComponentsInChildren<ParticleSystem>();
		foreach(ParticleSystem ps in particles)
		{
			ps.enableEmission = true;
			ps.Clear();
			ps.Play ();
		}
		Debug.LogError("AddSkillEffect  setEffPosition  "+skill_id);
		if(skillResInfo.needClearInSeconds>0)
		{
			StartCoroutine( CoRemoveSkillEffect(person, skill_id,  skillResInfo.needClearInSeconds ) );
		}
	}


	public void AddSkillEffect(BoardPerson person, int skill_id)
	{
		if(!needFX.ContainsKey(skill_id))
			return;

		if(needFX[skill_id].skillResPrefab!=null)
		{
			if( !skillEffInstance.ContainsKey(skill_id) )
			{
				skillEffInstance.Add (skill_id, new List<GameObject>() );
				CreateEffInstance(person, skill_id);

			}
			else
			{
				var list = skillEffInstance[skill_id];
				GameObject poolGo=null;
				foreach( GameObject go in list)
				{
					if(go.activeSelf && go.transform.parent == person.transform)
						return;//already have. return
					if(!go.activeSelf && poolGo==null)
					{
						poolGo=go;
					}
				}
				if(poolGo!=null)
				{
					poolGo.SetActive(true);
					SetEffPosition(poolGo, person, skill_id);
				}
				else
					CreateEffInstance(person, skill_id);
			}
		}
	}

	IEnumerator CoRemoveSkillEffect(BoardPerson person, int skill_id, float delay)
	{
		yield return new WaitForSeconds(delay);
		RemoveSkillEffect(person, skill_id);
	}

	public void RemoveSkillEffect(BoardPerson person, int skill_id)
	{
		if(skillEffInstance.ContainsKey(skill_id) )
		{
			var list = skillEffInstance[skill_id];
			foreach( GameObject go in list)
			{
				if(go.activeSelf && (go.transform.parent == person.transform || IsUnitcardParent(go,person) )  )
				{
//					Animator animator = go.GetComponent<Animator>();
//					if(animator!=null && animator.animation!=null)
//					{
//						glog.debug("### animation stop");
//						animator.animation.Stop();
//					}
					Debug.LogError("RemoveSkillEffect "+skill_id);
					if( needFX.ContainsKey(skill_id) && needFX[skill_id].isInstantDestroy)
					{	
						list.Remove(go);
						Destroy(go);
					}
					else
					{
						ParticleSystem [] particles = go.GetComponentsInChildren<ParticleSystem>();
						foreach(ParticleSystem ps in particles)
						{
							ps.Stop ();
							ps.enableEmission = false;
						}
						go.SetActive(false);
						go.transform.parent = instance.transform;
					}
					return;
				}
			}
		}
	}

	bool IsUnitcardParent(GameObject go, BoardPerson person)
	{
		if(go.transform.parent!=null)
		{
			UnitCard card = go.transform.parent.gameObject.GetComponent<UnitCard>();
			if(card!=null)
			{
				if(card.SID == person.SID)
					return true;
			}
		}
		return false;
	}

	public void RemoveSkillEffect(int sid, AbnormalType abType, int abParam)
	{
		int checkSkillID=-1;
		foreach(var pair in needFX)
		{
			if(pair.Value.abnormalType==abType && pair.Value.abnormalParam==abParam)
			{
				checkSkillID = pair.Key;
				if(needFX[checkSkillID].dontRemoveByAbnormal)
					return;
				break;
			}

		}
		if(checkSkillID!=-1)
		{
			RemoveSkillEffect( StageManagerWrapper.GetBoardPerson(sid), checkSkillID);
		}
	}

	public float waitSkillEffectClearTime(int skill_id)
	{
		if( needFX.ContainsKey(skill_id) )
		{
			return needFX[skill_id].needClearInSeconds;
		}
		return 0;
	}
	
}
